﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.ComponentModel;
using FinPlusCompCore;
using FinPlusAssembler;
using FinPlusInterfaces;

namespace FinPlusCompTradeParsers
{
    public class QLParseBondTrade : FinPlusComponent
    {
        private enum Params { ParseTradeAction, ResponseAction, Bond, BuySell, Instrument, Settle, QuoteAccept, QuoteRef, TradeId, Quote, Size, FixedRateBond, FloatingRateBond, ZeroCouponBond, Book, Counterparty, MarketName, CacheName, TempId, BondName, CurveName, Nominal, Settlement, Price }
        private enum BondBuilds { FixedRateBondBuild, FloatingRateBondBuild, ZeroCouponBondBuild, Bond }
        private readonly IFinPlusComp _instrumentBuildConn, _tradeAdapterConn;
        private readonly FinPlusConnectDB _tradeSaveConn;
        private readonly IPod _tradeAdapter;

        //construct
        public QLParseBondTrade(IFinPlusComp instrumentBuilds, IFinPlusComp tradeAdapters, IFinPlusComp tradeSave)
        {
            _instrumentBuildConn = instrumentBuilds;
            _tradeAdapterConn = tradeAdapters;
            _tradeSaveConn = (FinPlusConnectDB)tradeSave;
            _tradeAdapter = _tradeAdapterConn.Adapter.First("Name='InstrumentType' And Value='Bond'");
            _tradeAdapter.Get(Params.ParseTradeAction.ToString(), Parse_Trade);
            IsValid = true;
        }

        //common control interface
        public override void Dispose()
        {
            try
            {
                if (_tradeSaveConn != null)
                    _tradeSaveConn.Dispose();
            }
            catch (Exception e)
            {
                IsValid = Level.Warning.Log(Id, Config, e.Message, e);
            }
        }

        public override void CmdExecute(IPod command)
        {
            try
            {
                CmdCapture(command);

                switch ((Cmds)Enum.Parse(typeof(Cmds), command.Name, true))
                {
                    case Cmds.QuoteAccept: ExecutionParse(command); break;
                    case Cmds.QuoteAcceptPublish: ExecutionParse(command); break;
                    default: throw new FormatException(string.Format("cmd not recognised {0}", command.Name));
                }
            }
            catch (CmdExecuteException e)
            {
                IsValid = Level.Error.Log(Id, Config, e.Message, e);
            }
        }

        //private
        private void ExecutionParse(IPod pod)
        {
            try
            {
                //trade parse
                var instrument = pod[Params.Instrument.ToString()].ToString();
                var instrumentBuild = _instrumentBuildConn.Adapter.First("Name='Instrument' And Value='" + instrument + "'");

                IPod trade;
                switch (instrumentBuild[PodField.Type.ToString()].ToString().EnumParse<BondBuilds>(BondBuilds.Bond))
                {
                    case BondBuilds.FixedRateBondBuild: trade = IOC.New<IPod>(Params.FixedRateBond.ToString()); break;
                    case BondBuilds.FloatingRateBondBuild: trade =  IOC.New<IPod>(Params.FloatingRateBond.ToString()); break;
                    case BondBuilds.ZeroCouponBondBuild: trade = IOC.New<IPod>(Params.ZeroCouponBond.ToString()); break;
                    default: trade = IOC.New<IPod>(Params.Bond.ToString()); break;
                }

                trade.Add(Params.Book.ToString(), pod[Params.Book.ToString()].ToString());
                trade.Add(Params.Counterparty.ToString(), pod[Params.Counterparty.ToString()].ToString());
                trade.Add(Params.MarketName.ToString(), string.Empty);
                trade.Add(Params.CacheName.ToString(), string.Empty);
                trade.Add(Params.TradeId.ToString(), pod[Params.QuoteRef.ToString()].ToString());
                trade.Add(Params.BondName.ToString(), pod[Params.Instrument.ToString()].ToString());
                trade.Add(Params.CurveName.ToString(), string.Empty);

                if(pod.Name.Equals(Params.QuoteAccept.ToString()))
                    trade.Add(Params.Nominal.ToString(), (pod[Params.BuySell.ToString()].Equals("Buy") ? -1 : 1) * (double)pod.Value(Params.Size.ToString()));
                else
                    trade.Add(Params.Nominal.ToString(), (pod[Params.BuySell.ToString()].Equals("Buy") ? 1 : -1) * (double)pod.Value(Params.Size.ToString()));
                
                trade.Add(Params.Settlement.ToString(), (DateTime)pod.Value(Params.Settle.ToString()));
                trade.Add(Params.Price.ToString(), (double)pod.Value(Params.Quote.ToString()));

                //save bond
                _tradeSaveConn.Save(trade);

                //respond with trade for testing
                trade.Add(Params.Instrument.ToString(), instrument); 
                _tradeAdapter.Get(Params.ResponseAction.ToString()).Update(trade);
            }
            catch (Exception e)
            {
                IsValid = Level.Error.Log(Id, Config, pod.ToString(), e);
            } 
        }

        //cmds
        private enum Cmds { QuoteAccept, QuoteAcceptPublish };

        //events
        private void Parse_Trade(object s, PropertyChangedEventArgs a) { CmdRouter(s); }//QuoteAccept && QuotePublishAccept
    }
}
